package border;

import square.Direction;
import square.Square;
import square.TeleportationSquare;
import be.kuleuven.cs.som.annotate.Basic;
import be.kuleuven.cs.som.annotate.Model;

import be.kuleuven.cs.som.annotate.Raw;

/**
 * A class for constructing doors, attached to maximum 2 teleportation
 * squares.
 * 
 * @version	3.0
 * @author 	Inge Gielis <inge.gielis@student.kuleuven.be>
 * @author 	Annelies Ketelslegers <annelies.ketelslegers@student.kuleuven.be> 
 */

public class Door extends Border{
	
	/**
	 * Initialize this new door attached to the given teleportation squares 
	 * in the given direction and define the door as closed or not.
	 * 
	 * @param	isClosed
	 * 			The new closed state for this new door. 
	 * @post	If boolean isClosed is true, the door is set to be closed.
	 * 			If boolean isClosed is false, the door is set to be open.
	 * 			| new.isClosed() = isClosed
	 * @effect 	This new door is initialized as a border with the given squares 
	 * 			and the given direction.
	 * 			| super(square1, square2, direction)
	 */
	@Raw
	public Door(TeleportationSquare square1, TeleportationSquare square2, 
			Direction direction, boolean isClosed){
		super(square1, square2, direction);
		setClosed(isClosed);
	}
	
	/**
	 * Initialize this new door attached to the given teleportation square 
	 * in the given direction and define the door as closed or not.
	 * 
	 * @param	isClosed
	 * 			The new closed state for this new door.
	 * @post	If boolean isClosed is true, the door is set to be closed.
	 * 			If boolean isClosed is false, the door is set to be open.
	 * 			| new.isClosed() = isClosed
	 * @effect 	This new door is initialized as a border with the given 
	 * 			square and the given direction.
	 * 			| super(square, direction)
	 */
	@Raw
	public Door(TeleportationSquare square, Direction direction, 
			boolean isClosed) {
		super(square, direction);
		setClosed(isClosed);
	}

	/**
	 * Open the door.
	 * 
	 * @effect 	The closed state of this door is set to false.
	 * 			| setClosed(false)
	 */
	public void open(){
		setClosed(false);
		
	}
	
	/**
	 * Close the door.
	 * 
	 * @effect 	The closed state of this door is set to true.
	 * 			| setClosed(true)
	 */
	public void close(){
		setClosed(true);
	}
	
	/**
	 * Set the square to which this border is attached to the given square.
	 * 
	 * @param 	flag
	 * 			The new closed state for this door.
	 * @post	The new closed state of this door is equal to the given flag.
	 * 			| new.isClosed() == flag
	 */
	@Basic @Raw @Model
	private void setClosed(boolean flag){
		this.isClosed = flag;
	}
	
	/**
	 * Check whether this door is closed.
	 */
	@Basic 
	public boolean isClosed(){
		return isClosed;
	}
	
	/**
	 * Variable referencing whether this door is closed.
	 */
	private boolean isClosed;
	
	/**
	 * Check whether this door can have the given square as one of it squares.
	 * 
	 * @return 	If this door is terminated, true if and only if the given 
	 * 			square is not effective.
	 * 			|if (this.isTerminated())
	 *			|	result ==  (square == null)
	 * @return 	Otherwise, return true if and only if the square is not terminated 
	 * 			and if the given square has no more than 2.
	 * 			| result == ((square.getNbDoors()<=2) && (! square.isTerminated())) 
	 */
	@Override
	public boolean canHaveAsSquare(Square square){
		if (this.isTerminated())
			return square == null;
		return ((! square.isTerminated()) 
					 && square.getNbDoors()<=2);
	}
	
	/**
	 * Check whether the given direction is a valid direction for any door.
	 * It's impossible to have a door in the floor or ceiling of a square.
	 * 
	 * @return	True if and only if the given direction is effective and is not the direction CEILING or FLOOR.
	 * 			|result == (direction != null && direction != Direction.CEILING && direction != Direction.FLOOR)
	 */
	@Override
	public boolean isValidDirection(Direction direction){
		return (direction != null && direction != Direction.CEILING && direction != Direction.FLOOR);
	}
	
	/**
	 * Return a textual representation of this door.
	 * 
	 * @return	A string consisting of the word "Door:", followed
	 * 			by "closed" or "open", depending on the state of this door.
	 * 			| result.equals(
	 * 			|	"Door: " + (this.isClosed() ? "Closed" : "Open") +" \n")
	 */
	@Override
	public String toString() {
		String result = "Door: ";
		result += (this.isClosed() ? "Closed" : "Open") +" \n";
		return result;
	}

}
